#ifndef _EVALUEMAPPER_H_
#define _EVALUEMAPPER_H_

#include <buola/buola.h>
#include <map>

namespace buola {

template<typename tFrom,typename tTo>
class EValueMapper : public UUncopiable
{
public:
	virtual ~EValueMapper() {}
	virtual tTo Map(tFrom)=0;
};

template<typename tFrom,typename tTo>
class ELinearMapper : public EValueMapper<tFrom,tTo>
{
public:
	ELinearMapper(const tFrom &pSrcMin,const tFrom &pSrcMax,
				  const tTo &pDestMin,const tTo &pDestMax)
		:	mSrcMin(pSrcMin),
			mSrcMax(pSrcMax),
			mDestMin(pDestMin),
			mDestMax(pDestMax)
	{
	}
	
	void SetSrcRange(const tFrom &pMin,const tFrom &pMax)
	{
		mSrcMin=pMin;
		mSrcMax=pMax;
	}
	
	void SetDestRange(const tTo &pMin,const tTo &pMax)
	{
		mDestMin=pMin;
		mDestMax=pMax;
	}
	
	virtual tTo Map(tFrom pSrc)
	{
		return mDestMin+
			   ((pSrc-mSrcMin)/(mSrcMax-mSrcMin))*(mDestMax-mDestMin);
	}

	tFrom mSrcMin,mSrcMax;
	tTo mDestMin,mDestMax;
};

template<typename tFrom,typename tTo>
class ELogMapper : public EValueMapper<tFrom,tTo>
{
public:
	ELogMapper(const tFrom &pSrcMin,const tFrom &pSrcMax,
				  const tTo &pDestMin,const tTo &pDestMax)
		:	mSrcMin(pSrcMin),
			mSrcMax(pSrcMax),
			mDestMin(pDestMin),
			mDestMax(pDestMax)
	{
	}
	
	void SetSrcRange(const tFrom &pMin,const tFrom &pMax)
	{
		mSrcMin=pMin;
		mSrcMax=pMax;
	}
	
	void SetDestRange(const tTo &pMin,const tTo &pMax)
	{
		mDestMin=pMin;
		mDestMax=pMax;
	}
	
	virtual tTo Map(tFrom pSrc)
	{
		return mDestMin+(log(pSrc/mSrcMin)/log(mSrcMax/mSrcMin))*
								(mDestMax-mDestMin);
	}

	tFrom mSrcMin,mSrcMax;
	tTo mDestMin,mDestMax;
};

template<typename tFrom,typename tTo>
class EDiscreteMapper : public EValueMapper<tFrom,tTo>
{
public:
	EDiscreteMapper()
	{
	}
	
	void AddPair(tFrom pFrom,const tTo &pTo)
	{
		mDict[pFrom]=pTo;
	}
	
	void SetDefaultValue(const tTo &pTo)
	{
		mDefault=pTo;
	}
	
	virtual tTo Map(tFrom pSrc)
	{
		typename std::map<tFrom,tTo>::iterator i=mDict.find(pSrc);
		
		if(i!=mDict.end())
		{
			return i->second;
		}
		else
		{
			return mDefault;
		}
	}

	tTo mDefault;
	std::map<tFrom,tTo> mDict;
};

/*namespace buola*/ }

#endif
